﻿using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Ccit.Utils
{
    /// <summary>
    /// 日期操作类
    /// </summary> 
    public class DateLib
    {
        private string _innerDateTime;

        #region 属性
        /// <summary>
        /// 当前日期对象
        /// </summary>
        public LocalNow Now
        {
            get { return new LocalNow(); }   
        }

        /// <summary>
        /// 年份
        /// </summary>
        public string year
        {
            get
            {
                if (_innerDateTime.Length >= 4)
                    return _innerDateTime.Substring(0, 4);
                else
                {
                    return "";
                }
            }
        }

        /// <summary>
        /// 月份
        /// </summary>
        public string month
        {
            get
            {
                if (_innerDateTime.Length >= 7)
                    return _innerDateTime.Substring(5, 2);
                else
                {
                    return "";
                }
            }
        }

        /// <summary>
        /// 日
        /// </summary>
        public string day
        {
            get
            {
                if (_innerDateTime.Length >= 10)
                    return _innerDateTime.Substring(8, 2);
                else
                {
                    return "";
                }
            }
        }

        /// <summary>
        /// 时间
        /// </summary>
        public string Time
        {
            get
            {
                if (_innerDateTime.Length >= 16)
                    return _innerDateTime.Substring(11);
                else
                    return "";
            }
        }

        #endregion


        #region 构造函数
        /// <summary>
        /// 用指定日期初始化对象
        /// </summary>
        /// <param name="sDateTime"></param>
        public DateLib(string sDateTime)
        {
            try
            {
                DateTime cnvtDateTime = DateTime.Parse(sDateTime);
                _innerDateTime = cnvtDateTime.ToString("yyyy-MM-dd HH:mm:ss");

            }
            catch
            {
                throw new Exception("convert DateTime is Failed!");
            }

        }

        /// <summary>
        /// 默认以当前日期初始化对象
        /// </summary>
        public DateLib()
        {
            LocalNow lcNow = new LocalNow();
            _innerDateTime = lcNow.ToString(FormatType.second);
        }

        #endregion


        #region 公开接口
        /// <summary>
        /// 以默认格式(YYYY-MM-DD HH:MM)输出日期
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            DateTime cnvtDateTime = DateTime.Parse(_innerDateTime);
            return cnvtDateTime.ToString("yyyy-MM-dd HH:mm");   
        }

        /// <summary>
        /// 以指定格式输出日期
        /// </summary>
        /// <param name="formatType">格式枚举</param>
        /// <returns></returns>
        public string ToString(FormatType formatType)
        {
            string sReturnDateTime = "";
            DateTime cnvtDateTime = DateTime.Parse(_innerDateTime);
            switch (formatType)
            {
                case FormatType.date:
                    sReturnDateTime = cnvtDateTime.ToString("yyyy-MM-dd");
                    break;
                case FormatType.standard:
                    sReturnDateTime = cnvtDateTime.ToString("yyyy-MM-dd HH:mm");
                    break;
                case FormatType.second:
                    sReturnDateTime = cnvtDateTime.ToString("yyyy-MM-dd HH:mm:ss");
                    break;
            }

            return sReturnDateTime;
        }

        /// <summary>
        /// 输出日期的DateTime对象表示
        /// </summary>
        /// <returns></returns>
        public DateTime ToDateTime()
        {
            return DateTime.Parse(ToString(FormatType.date));
        }

        /// <summary>
        /// 获取日期所在周的第一天(星期一)的日期
        /// </summary>
        /// <returns>
        /// 传入日期所在周的第一天的日期(以"YYYY-MM-DD"格式返回)
        /// </returns>
        public string GetFirstDateOfWeek()
        {
            return GetDateByDayNoOfWeek(1);
        }

        /// <summary>
        ///	获取日期所在周的第一天(星期一)的日期
        /// </summary>
        /// <returns>
        ///	传入日期所在周的最后一天的日期(以"YYYY-MM-DD"格式返回)
        /// </returns>
        public string GetLastDateOfWeek()
        {
            return GetDateByDayNoOfWeek(7);
        }	

        /// <summary>
        ///		根据传入日期以及指定的星期几返回该日期所在周的指定星期几的日期
        ///		以"YYYY-MM-DD"格式返回
        /// </summary>
        /// <param name="DayNoOfWeek">
        ///		指定的星期几(1周一,2表示周二... 7表示周日)
        /// </param>
        /// <returns>
        ///		传入日期所在周的指定星期几的日期(以"YYYY-MM-DD"格式返回)
        /// </returns>
        public string GetDateByDayNoOfWeek(int DayNoOfWeek)
        {
            string rDate = "";
            DateTime dDate;
            try
            {
                dDate = DateTime.Parse(ToString(FormatType.date));
            }
            catch
            {
                return rDate;
            }
            int iflag = GetNoOfWeek(dDate.DayOfWeek.ToString());
            if (iflag >= 1)
                rDate = dDate.AddDays(DayNoOfWeek - iflag).ToString();

            DateLib dtlInstance = new DateLib(rDate);
            rDate = dtlInstance.ToString(FormatType.date);
            return rDate;
        }

        /// <summary>
        ///		根据星期几的名称返回该天对应的整数
        ///		1表示星期一,2表示星期二... 7表示星期日
        /// </summary>
        /// <param name="WeekName">
        ///		周一到周日的星期参数，字符串
        ///		Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday 分别表示星期一至星期日
        /// </param>
        /// <returns>
        ///		整数(1表示星期一,2表示星期二... 7表示星期日)
        /// </returns>
        public int GetNoOfWeek(string WeekName)
        {
            int ii = -1;
            if (WeekName == "Sunday")
                ii = 7;
            else if (WeekName == "Monday")
                ii = 1;
            else if (WeekName == "Tuesday")
                ii = 2;
            else if (WeekName == "Wednesday")
                ii = 3;
            else if (WeekName == "Thursday")
                ii = 4;
            else if (WeekName == "Friday")
                ii = 5;
            else if (WeekName == "Saturday")
                ii = 6;

            return ii;
        }

        /// <summary>
        /// 根据日期所在周星期几的英文名称获取相应的中文名称
        /// </summary>
        /// <param name="weekName">日期所在周星期几的英文名称</param>
        /// <returns></returns>
        public string GetChineseDesc(string weekName)
        {
            string chineseName = string.Empty;
            if (weekName == "Sunday")
                chineseName = "星期日";
            else if (weekName == "Monday")
                chineseName = "星期一";
            else if (weekName == "Tuesday")
                chineseName = "星期二";
            else if (weekName == "Wednesday")
                chineseName = "星期三";
            else if (weekName == "Thursday")
                chineseName = "星期四";
            else if (weekName == "Friday")
                chineseName = "星期五";
            else if (weekName == "Saturday")
                chineseName = "星期六";

            return chineseName;
        }

        /// <summary>
        ///	获取所在月的最后一天的日期
        /// </summary>
        /// <returns>
        ///	所在月的最后一天日期(以"YYYY-MM-DD"格式返回)
        /// </returns>
        public string GetEndDateOfMonth()
        {
            string rDate = "";
            DateTime dDate = DateTime.Parse(ToString(FormatType.date));
           
            int iYear = dDate.Year;
            int iMonth = dDate.Month;
            iYear = (iMonth == 12) ? iYear + 1 : iYear;
            iMonth = (iMonth == 12) ? 1 : iMonth + 1;
            dDate = DateTime.Parse((iYear.ToString() + "-" + iMonth.ToString() + "-1"));
            dDate = dDate.AddDays(-1);
            DateLib dtlInstance = new DateLib(dDate.ToString());
            rDate = dtlInstance.ToString(FormatType.date);
            
            return rDate;
        }

        /// <summary>
        ///	获取所在月的第一天的日期
        /// </summary>
        /// <returns>
        ///	所在月的第一天日期(以"YYYY-MM-DD"格式返回)
        /// </returns>
        public string GetFirstDateOfMonth()
        {
            string sReturnDate = year + "-" + month + "-01";
            return sReturnDate;
        }

        /// <summary>
        ///	加上指定的天数之后的日期
        /// </summary>
        /// <param name="Days">需要在指定日期上加上的天数</param>
        /// <returns></returns>
        public void Add(int Days)
        {
            TimeSpan timeSpan = new TimeSpan(Days, 0, 0, 0);
            DateTime dtResult = ToDateTime() + timeSpan;
            _innerDateTime = dtResult.ToString("yyyy-MM-dd") + _innerDateTime.Substring(10);
        }

        /// <summary>
        ///	减去指定的天数之后的日期
        /// </summary>
        /// <param name="Days">需要在指定日期上减去的天数</param>
        /// <returns></returns>         
        public void Subtract(int Days)
        {
            TimeSpan timeSpan = new TimeSpan(Days, 0, 0, 0);
            DateTime dtResult = ToDateTime() - timeSpan;
            _innerDateTime = dtResult.ToString("yyyy-MM-dd") + _innerDateTime.Substring(10);
        }	

        #endregion


        #region 静态公开方法
        /// <summary>
        /// 格式化日期
        /// </summary>
        /// <param name="UnFormatDate">待格式化的日期</param>
        /// <param name="FormatExpression">格式化表达式</param>
        /// <returns></returns>
        public static string FormatDate(string UnFormatDate, string FormatExpression)
        {
            if (string.IsNullOrEmpty(UnFormatDate)) return "";

            string sFormatDate = UnFormatDate;
            string sFormatExpr = FormatExpression;
            sFormatExpr = sFormatExpr.Replace("mm", "MM");
            sFormatExpr = sFormatExpr.Replace("nn", "mm");
            sFormatExpr = sFormatExpr.Replace("hh", "HH");	//HH表示24小时显示方式
            System.DateTime SystemTime = DateTime.Parse(sFormatDate);

            return SystemTime.ToString(sFormatExpr);
        }

        /// <summary>
        ///		计算开始日期和结束日期之间相差的天数,如果开始日期大于结束日期,返回相应的负数
        /// </summary>
        /// <param name="StartDate">开始日期,如果为空,取当前日期</param>
        /// <param name="EndDate">结束日期,如果为空,取当前日期</param>
        /// <returns>开始日期和结束日期之间相差的天数</returns>
        public static int DateDiff(string StartDate, string EndDate)
        {
            DateLib dtlStart;
            DateLib dtlEnd;

            if(string.IsNullOrEmpty(StartDate))
                dtlStart = new DateLib();
            else
                dtlStart = new DateLib(StartDate);

            if (string.IsNullOrEmpty(EndDate))
                dtlEnd = new DateLib();
            else
                dtlEnd = new DateLib(EndDate);

            System.TimeSpan timeSpan = dtlEnd.ToDateTime().Subtract(dtlStart.ToDateTime());
            int iReturnValue = timeSpan.Days;

            dtlStart = null;
            dtlEnd = null;
            return iReturnValue;
        }

        /// <summary>
        /// 获取系统当前时间
        /// </summary>
        /// <returns></returns>
        public static string GetSysCurDateTime(FormatType formatType)
        {
            string sReturnDateTime = "";
            switch (formatType)
            {
                case FormatType.date:
                    sReturnDateTime = DateTime.Now.ToString("yyyy-MM-dd");
                    break;
                case FormatType.standard:
                    sReturnDateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm");
                    break;
                case FormatType.second:
                    sReturnDateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                    break;
            }

            return sReturnDateTime;
        }

        /// <summary>
        /// 获取传入日期所在周的星期几中文描述
        /// </summary>
        /// <param name="date">传入日期</param>
        /// <returns></returns>
        public static string GetDayOfWeekChineseDesc(string date)
        {
            string dayOfWeekDesc = string.Empty;           
            try
            {
                DateTime cnvtDateTime = DateTime.Parse(date);
                DateTime dDate = DateTime.Parse(cnvtDateTime.ToString("yyyy-MM-dd"));
                dayOfWeekDesc = GetChineseDescByWeekName(dDate.DayOfWeek.ToString());
            }
            catch
            {
                return "";
            }

            return dayOfWeekDesc;
        }
        
        #endregion

        #region private static interface
        /// <summary>
        /// 根据日期所在周星期几的英文名称获取相应的中文名称
        /// </summary>
        /// <param name="weekName">日期所在周星期几的英文名称</param>
        /// <returns></returns>
        private static string GetChineseDescByWeekName(string weekName)
        {
            string chineseName = string.Empty;
            if (weekName == "Sunday")
                chineseName = "星期日";
            else if (weekName == "Monday")
                chineseName = "星期一";
            else if (weekName == "Tuesday")
                chineseName = "星期二";
            else if (weekName == "Wednesday")
                chineseName = "星期三";
            else if (weekName == "Thursday")
                chineseName = "星期四";
            else if (weekName == "Friday")
                chineseName = "星期五";
            else if (weekName == "Saturday")
                chineseName = "星期六";

            return chineseName;
        }
        #endregion

    }

    /// <summary>
    /// 本地当前日期类
    /// </summary>
    public class LocalNow
    {
        /// <summary>
        /// 默认构造函数
        /// </summary>
        public LocalNow() { }

        /// <summary>
        /// 以默认格式(YYYY-MM-DD HH:MM) 输出当前日期
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return DateTime.Now.ToString("yyyy-MM-dd HH:mm");
        }

        /// <summary>
        /// 以指定格式输出当前日期
        /// </summary>
        /// <param name="formatType">格式枚举</param>
        /// <returns></returns>
        public string ToString(FormatType formatType)
        {
            string sReturnDateTime = "";
            switch(formatType)
            {
                case FormatType.date:
                    sReturnDateTime = DateTime.Now.ToString("yyyy-MM-dd");
                    break;
                case FormatType.standard:
                    sReturnDateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm");
                    break;
                case FormatType.second:
                    sReturnDateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                    break;
            }

            return sReturnDateTime;
        }
    }

    /// <summary>
    /// 格式枚举类型
    /// </summary>
    public enum FormatType
    {        
        /// <summary>
        /// yyyy-MM-dd
        /// </summary>
        date = 1,
        /// <summary>
        /// yyyy-MM-dd HH:mm (标准格式)
        /// </summary>
        standard = 2,
        /// <summary>
        /// yyyy-MM-dd HH:mm:ss
        /// </summary>
        second = 3
    }

    
}
